#ifndef __GMATLAB_H__
#define __GMATLAB_H__

#include <glib-object.h>
#include <girepository.h>
#include <matrix.h>
#include <gmatlab-conf.h>

// SIZEOF_INT determined during configure
#if SIZEOF_INT == 1
#define MX_GINT mxINT8_CLASS
#define MX_GUINT mxUINT8_CLASS
#endif
#if SIZEOF_INT == 2
#define MX_GINT mxINT16_CLASS
#define MX_GUINT mxUINT16_CLASS
#endif
#if SIZEOF_INT == 4
#define MX_GINT mxINT32_CLASS
#define MX_GUINT mxUINT32_CLASS
#endif
#if SIZEOF_INT == 8
#define MX_GINT mxINT64_CLASS
#define MX_GUINT mxUINT64_CLASS
#endif

#if GLIB_SIZEOF_LONG == 1
#define MX_GLONG mxINT8_CLASS
#define MX_GULONG mxUINT8_CLASS
#endif
#if GLIB_SIZEOF_LONG == 2
#define MX_GLONG mxINT16_CLASS
#define MX_GULONG mxUINT16_CLASS
#endif
#if GLIB_SIZEOF_LONG == 4
#define MX_GLONG mxINT32_CLASS
#define MX_GULONG mxUINT32_CLASS
#endif
#if GLIB_SIZEOF_LONG == 8
#define MX_GLONG mxINT64_CLASS
#define MX_GULONG mxUINT64_CLASS
#endif

#if GLIB_SIZEOF_VOID_P == 8
#define MX_GPOINTER mxUINT64_CLASS
#else
#define MX_GPOINTER mxUINT32_CLASS
#endif

G_BEGIN_DECLS

// Note: format must be a string literal, not a variable.
// Note: must have at least one argument after format string.
// Use this instead of g_debug to prevent recursive g_log aborts.
#if 1
#define TRACE(format, ...) mexPrintf(format "\n", __VA_ARGS__)
#else
#define TRACE(...) 
#endif

// gmatlab.c
void g_matlab_init();
void g_irepository_matlab_load_pkg(const gchar *name);
mxArray *g_irepository_matlab_find_symbol(gchar *ns, gchar *name);
mxArray *g_irepository_matlab_find_method(GIBaseInfo *type, gchar *name);
mxArray * g_object_matlab_get_property(GObject *obj, gchar *name);
void g_object_matlab_set_property(GObject *obj, gchar *name, mxArray *mxValue);
mxArray * g_irepository_matlab_invoke(GIFunctionInfo *func, mxArray *mxArgs);

// gmaterr.c
void g_matlab_error(const gchar *id, const gchar *format, ...);
void g_matlab_error_with_error(const gchar *id, GError *err, const gchar *format, ...);
void g_matlab_log_func(const gchar *log_domain, GLogLevelFlags log_level,
                       const gchar *message, gpointer user_data);

// gmattype.c
gpointer g_matlab_mxArray_get_pointer(mxArray *mxValue);
gchar * g_matlab_mxArray_get_utf8(mxArray *value);
mxArray *g_matlab_mxArray_from_utf8(const gchar *value);
mxArray *g_matlab_sprintf(const char *format, ...);
GType g_matlab_mxArray_common_get_gtype(mxArray *value);
mxArray *g_matlab_mxArray_from_giInfo(GIBaseInfo *info);
GType g_matlab_mxArray_get_gtype(mxArray *value);
mxArray * g_matlab_mxArray_from_gtype(GType gtype);
gpointer g_matlab_mxArray_get_boxed(mxArray *value);
mxArray * g_matlab_mxArray_from_boxed(GType type, gpointer data);
guint g_matlab_mxArray_get_enum(mxArray *value);
mxArray * g_matlab_mxArray_from_enum(GType type, guint data);
guint g_matlab_mxArray_get_flags(mxArray *value);
mxArray * g_matlab_mxArray_from_flags(GType type, guint data);
GObject * g_matlab_mxArray_get_object(mxArray *value);
gboolean g_matlab_check_class(mxArray *obj, const gchar *cls);
void g_value_from_mxArray(GValue *value, mxArray *mxValue);
mxArray * g_value_to_mxArray(GValue *value);
void g_arg_from_mxArray(GArgument *arg, GITypeInfo *info,
                        mxArray *value, GITransfer transfer, int n);
mxArray * g_arg_to_mxArray(GArgument *arg, GIBaseInfo *type,
                           GITransfer transfer);
gboolean arg_set_from_mxArray(GArgument *arg, GITypeTag type, 
                              gpointer data, mxClassID mxType, guint j);
gboolean arg_set_mxArray(GArgument *arg, GITypeTag type, 
                         gpointer data, mxClassID mxType, guint j);

// gmatmem.c
gpointer g_matlab_cleanup_add(GHookFunc func, gpointer data);
void g_matlab_cleanup();
void g_matlab_escape_init();
gpointer g_matlab_escape_add(GHookFunc, gpointer);
void g_matlab_escape_clear_one(gpointer);
void g_matlab_escape_clear();
void g_matlab_cleanup_push();
void g_matlab_cleanup_pop();
void g_object_matlab_ensure(GObject *obj, mxArray *wrapper);
mxArray * g_object_matlab_wrap(GObject *obj);
void g_object_matlab_remove_toggle_ref(GObject *obj);

// gmatsig.c
GClosure *g_closure_matlab_new(mxArray *func, mxArray *user_data);
void g_signal_matlab_connect(GObject *obj, const gchar *signal, mxArray *func,
                             mxArray *data, gboolean after);
//mxArray *g_closure_matlab_invoke(GClosure *closure, mxArray *args);

G_END_DECLS
#endif
